import datetime
import pytz

import coin.exchange.base.kr_rest.public_client_base as pubcb
import coin.exchange.bybit.kr_rest.native_public_client as npubc
from coin.exchange.bybit.kr_rest.futures_product import BybitFuturesProduct
from coin.proto.coin_market_query_pb2 import (
    ProductKline,
    ProductKlineElement)


class BybitFeedParser(object):
  @staticmethod
  def parse_native_kline(update_msg, product, kline_period, start_time, end_time):
    """Sample kline response:
      {
        "ret_code": 0,
        "ret_msg": "OK",
        "ext_code": "",
        "ext_info": "",
        "result": [{
            "symbol": "BTCUSD",
            "interval": "1",
            "open_time": 1581231300,
            "open": "10112.5",
            "high": "10112.5",
            "low": "10112",
            "close": "10112",
            "volume": "75981",
            "turnover": "7.51394369"
        }, {
            "symbol": "BTCUSD",
            "interval": "1",
            "open_time": 1581231360,
            "open": "10112",
            "high": "10112.5",
            "low": "10112",
            "close": "10112",
            "volume": "24616",
            "turnover": "2.4343353100000003"
        }],
        "time_now": "1581928016.558522"
    }
    """
    assert update_msg['ret_code'] == 0 and update_msg['ret_msg'] == 'OK'
    klines = update_msg['result']
    kline_group = []
    for kline in klines:
      kline_timestamp = kline['open_time']
      if kline_timestamp >= start_time.timestamp() and \
         kline_timestamp < end_time.timestamp():
        product_kline = ProductKlineElement(kline_timestamp=int(kline_timestamp * 1e+9),
                                            open=float(kline['open']),
                                            high=float(kline['high']),
                                            low=float(kline['low']),
                                            close=float(kline['close']),
                                            volume=float(kline['volume']),
                                            turnover=float(kline['turnover']))
        kline_group.append(product_kline)
    assert len(kline_group) > 0
    return ProductKline(
        symbol=product.symbol,
        native_symbol=product.native_symbol,
        exchange='Bybit',
        market_type='Futures',
        klines=kline_group,
    )

class BybitPublicClient(pubcb.PublicClientBase):
  ProductType = BybitFuturesProduct

  def __init__(self):
    self.npubc = npubc.BybitNativePublicClient()

  def query_history_kline_impl(self, product, kline_period, start_time, end_time):
    native_symbol = product.native_symbol
    start_time = start_time.replace(tzinfo=pytz.UTC)
    end_time = end_time.replace(tzinfo=pytz.UTC)
    update = self.npubc.get_history_kline(
        native_symbol, kline_period, start_time)
    update.msg = BybitFeedParser.parse_native_kline(update.msg,
                                                    product,
                                                    kline_period,
                                                    start_time,
                                                    end_time)
    return update

  def query_level_book_impl(self, product):
    raise NotImplementedError("Bybit query level book Not Implemented")

if __name__ == "__main__":
  client = BybitPublicClient()
  start_time = datetime.datetime(2021, 2, 7).replace(tzinfo=pytz.UTC)
  end_time = datetime.datetime(2021, 2, 7, 1, 59, 59).replace(tzinfo=pytz.UTC)
  print(client.query_history_kline(
      BybitFuturesProduct.FromStr('BTC-USD.PERPETUAL'), '60', start_time, end_time).msg)
  print(client.query_history_kline(
      BybitFuturesProduct.FromStr('BTC-USDT.PERPETUAL'), '60', start_time, end_time).msg)
